package process

import (
	"code.project.com/chatroom/client/utils"
	"code.project.com/chatroom/common/message"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"net"
	"os"
)

// 处理用户消息的
// 关联用户登录的方法
type UserProcess struct {
}

// 写一个函数, 完成登录
func (u *UserProcess) Login(userId int, userPwd string) (err error) {
	//开始定义协议..
	//fmt.Printf("userId = %d userPwd = %s",userId,userPwd)
	// 1.链接到服务器端
	conn, err := net.Dial("tcp", ":8889")
	// conn 延时关闭
	defer conn.Close()

	if err != nil {
		fmt.Println("与服务器连接失败")
		return
	}

	// 2.准备通过conn 发送消息给服务器
	var mes message.Message
	mes.Type = message.LoginMesType

	// 3.创建一个loginMes 结构体
	var loginMes message.LoginMes
	loginMes.UserId = userId
	loginMes.UserPwd = userPwd

	// 4. 讲loginMes 序列化
	data, err := json.Marshal(loginMes)
	if err != nil {
		fmt.Println("消息创建失败")
		return
	}
	// data 赋给 mes.Data 字段
	mes.Data = string(data)


	// 将 mes 序列化
	data, err = json.Marshal(mes)
	if err != nil {
		fmt.Println("发送消息的结构体序列化失败")
		return
	}

	//7. 这个时候消息就是我们要发送的消息
	// 7.1 先把消息的 data长度发送给服务器
	// 现获取data的长度 -> 一个可以表示长度的其其切片
	var pkgLen uint32
	pkgLen = uint32(len(data))

	var buf [4]byte
	binary.BigEndian.PutUint32(buf[0:4], pkgLen)
	n, err := conn.Write(buf[:4])
	if n != 4 || err != nil {
		fmt.Println("发送长度信息失败!")
		return
	}
	fmt.Printf("客户端发送消息长度= %d\n 内容=%s", len(data), string(data))
	//"{\"userId\":100,\"userPwd\":\"123456\",\"userName\":\"scott\"}"

	// 发送消息本身
	_, err = conn.Write(data)
	if err != nil {
		fmt.Println("发送信息失败!")
		return
	}

	fmt.Println("发送登录消息")

	// 这里还需要处理与服务器返回的消息
	// 创建一个Transfer实例
	tf := &utils.Transfer{
		Conn: conn,
	}
	mes, err = tf.ReadPkg()
	if err != nil {
		fmt.Println("读取接受包失败")
		return
	}
	// 讲 mes 的Data部分反序列化成 LoginResMsg
	var loginResMsg message.LoginReMsg
	err = json.Unmarshal([]byte(mes.Data), &loginResMsg)

	if loginResMsg.Code == 200 {
		// 初始化CurrentUser
		currentUser.Conn = conn
		currentUser.UserId = userId
		currentUser.UserStatus = message.UserOnline

		// fmt.Println("登陆成功")
		// 显示当前用户在线的列表 遍历 loginReMsg.UserId
		fmt.Println("当前用户在线列表如下:")
		for _, v :=range loginResMsg.UsersId{
			// 不显示自己
			if v == userId{
				continue
			}
			// 显示其他人
			fmt.Println("用户Id:\t",v)
			// 完成 onlineUsers 完成初始化
			user := &message.User{
				UserId:     v,
				UserStatus: message.UserOnline,
			}
			onlineUsers[v] = user
		}
		fmt.Printf("\n\n")
		// 循环显示菜单
		go serverProcessMsg(conn)
		for {
			ShowMenu()
		}
	} else {
		fmt.Println(loginResMsg.Error)
	}
	return
}

func (u *UserProcess)Register(userId int, userPwd string, userName string) (err error)  {
	//开始定义协议..
	//fmt.Printf("userId = %d userPwd = %s",userId,userPwd)
	// 1.链接到服务器端
	conn, err := net.Dial("tcp", ":8889")
	// conn 延时关闭
	defer conn.Close()

	if err != nil {
		fmt.Println("与服务器连接失败")
		return
	}

	// 2.准备通过conn 发送消息给服务器
	var mes message.Message
	mes.Type = message.RegisterMesType

	// 3.创建一个loginMes 结构体
	var registerMes message.RegisterMes
	registerMes.User.UserId = userId
	registerMes.User.UserPwd = userPwd
	registerMes.User.UserName = userName

	// 4. registerMes 序列化
	data, err := json.Marshal(registerMes)
	if err != nil {
		fmt.Println("消息创建失败")
		return
	}
	// 5. data 赋给 mes.Data 字段
	mes.Data = string(data)


	// 6. 将 mes 序列化
	data, err = json.Marshal(mes)
	if err != nil {
		fmt.Println("发送消息的结构体序列化失败")
		return
	}

	//7. 这个时候消息就是我们要发送的消息
	// 7.1 先把消息的 data长度发送给服务器
	// 现获取data的长度 -> 一个可以表示长度的其其切片

	// 这里还需要处理与服务器返回的消息
	// 创建一个Transfer实例
	tf := &utils.Transfer{
		Conn: conn,
	}
	err = tf.WritePkg(data)
	if err != nil {
		fmt.Println("注册发送信息出错 err= ",err)
		return
	}

	mes, err = tf.ReadPkg()  // 读取注册返回结果 RegisterResMes
	if err != nil {
		return
	}
	// 讲 mes 的Data部分反序列化成 LoginResMsg
	var registerResMsg message.RegisterResMsg
	err = json.Unmarshal([]byte(mes.Data), &registerResMsg)

	if registerResMsg.Code == 200 {
		fmt.Println("注册成功")
		fmt.Println("重新登录吧")
		os.Exit(0)

	} else {
		fmt.Println(registerResMsg.Error)
		os.Exit(0)
	}

	return
}
